/*
 * Printer.cpp
 *
 *  Created on: 27/ott/2013
 *      Author: angelo
 */

#include "Printer.h"


const char* Printer::COLOR_LIST_10[] = {
		"green",
		"blue",
		"red",
		"gold",
		"magenta",
		"brown",
		"black",
		"darkorange",
		"salmon",
		"greenyellow"
};


Printer::Printer(char *fileName_base, Config *conf) {

	/* initialize random seed: */
	srand (time(NULL));

	nChannels = conf->nChannels;

	for(int i = 0; i < nChannels; i++){
		colorList[i] = rand() % 0xFFFFFF;
	}

	log_level = conf->logLevel;

	configuration = conf;

	//strncpy ( base_filename, fileName_base, sizeof(base_filename) );
	snprintf(base_filename, sizeof(base_filename), "%s", fileName_base);
}

Printer::~Printer() {
	// TODO Auto-generated destructor stub
}

bool Printer::checkLogLevel(Config::LOG_LEVELS ll) {
	return (ll <= log_level);
}

void Printer::printOutRamdomMap(EnvironmentArea *ea) {
	FILE *fileDOT;
	char buff[B_SIZE];
	int nBuff;

	list<Survivor *>::iterator it_s;

	if (!checkLogLevel(Config::LOG_HIGH)) return;

	snprintf(str_buff, sizeof(str_buff), "%s_RandomMapCreated.txt", base_filename);

	fileDOT = fopen(str_buff, "w");
	if (fileDOT) {

		// stampo tutti i punti dei sopravvissuti
		for (it_s = ea->survivors.begin(); it_s != ea->survivors.end(); it_s++) {
			nBuff = snprintf(buff, B_SIZE,
					"%lf;%lf;%i\r\n", (*it_s)->pos.x, (*it_s)->pos.y, (*it_s)->survivor_channel);

			fwrite(buff, 1, nBuff, fileDOT);
		}

		fclose (fileDOT);
	}
}

void Printer::printOutSurvivorsMap(EnvironmentArea *ea) {
	FILE *fileDOT;
	char buff[B_SIZE];
	int nBuff;

	list<Survivor *>::iterator it_s;

	if (!checkLogLevel(Config::LOG_HIGH)) return;

	snprintf(str_buff, sizeof(str_buff), "%s_SurvivorsMap.dot", base_filename);

	fileDOT = fopen(str_buff, "w");
	if (fileDOT) {

		nBuff = snprintf(buff, B_SIZE, "graph G{\r\n");
		fwrite(buff, 1, nBuff, fileDOT);

		// stampo i quattro angoli
		nBuff = snprintf(buff, B_SIZE, "{node [style=invis] P00 P01 P10 P11}\r\n");
		fwrite(buff, 1, nBuff, fileDOT);
		nBuff = snprintf(buff, B_SIZE, "P00 [pos=\"0,0!\"]\r\n");
		fwrite(buff, 1, nBuff, fileDOT);
		nBuff = snprintf(buff, B_SIZE, "P01 [pos=\"0,%lf!\"]\r\n", (double)ea->maxY);
		fwrite(buff, 1, nBuff, fileDOT);
		nBuff = snprintf(buff, B_SIZE, "P10 [pos=\"%lf,0!\"]\r\n", (double)ea->maxX);
		fwrite(buff, 1, nBuff, fileDOT);
		nBuff = snprintf(buff, B_SIZE, "P11 [pos=\"%lf,%lf!\"]\r\n\r\n", (double)ea->maxX, (double)ea->maxY);
		fwrite(buff, 1, nBuff, fileDOT);

		//nBuff = snprintf(buff, B_SIZE, "P00 -- P01\r\nP01 -- P11\r\nP11 -- P10\r\nP10 -- P00\r\n\r\n");
		//fwrite(buff, 1, nBuff, fileDOT);

		// disegno tutti i punti dei sopravvissuti
		for (it_s = ea->survivors.begin(); it_s != ea->survivors.end(); it_s++) {
			if (colorList.size() > 10) {
				nBuff = snprintf(buff, B_SIZE,
						"S%i [shape=\"point\" color=\"#%06X\" pos=\"%lf,%lf!\" width=3, height=3]\r\n",
						(*it_s)->survivor_id, colorList[(*it_s)->survivor_channel],
						(*it_s)->pos.x, (*it_s)->pos.y);
			}
			else {
				nBuff = snprintf(buff, B_SIZE,
						"S%i [shape=\"point\" color=\"%s\" pos=\"%lf,%lf!\" width=3, height=3]\r\n",
						(*it_s)->survivor_id, COLOR_LIST_10[(*it_s)->survivor_channel],
						(*it_s)->pos.x, (*it_s)->pos.y);

			}
			fwrite(buff, 1, nBuff, fileDOT);
		}

		nBuff = snprintf(buff, B_SIZE, "}");
		fwrite(buff, 1, nBuff, fileDOT);

		fclose (fileDOT);
	}

}

void Printer::printOutStemIslands_GENERIC(StemIslands *si, EnvironmentArea *ea, int algo_idx) {
	char buffFname[64];

	if (algo_idx < N_ALGO){
		snprintf(buffFname, sizeof(buffFname), "StemIslands_%s", Config::ALGO_NAME[algo_idx]);
	}
	else {
		snprintf(buffFname, sizeof(buffFname), "StemIslands_default");
	}

	printOutStemIslands_BOTH(si, ea, buffFname);
}

void Printer::printOutStemIslands_SCR(StemIslands *si, EnvironmentArea *ea) {
	char buffFname[64];

	snprintf(buffFname, sizeof(buffFname), "StemIslands_SCR");
	printOutStemIslands_BOTH(si, ea, buffFname);
}

void Printer::printOutStemIslands_SCD(StemIslands *si, EnvironmentArea *ea) {
	char buffFname[64];

	snprintf(buffFname, sizeof(buffFname), "StemIslands_SCD");
	printOutStemIslands_BOTH(si, ea, buffFname);

}

void Printer::printOutStemIslands_BOTH(StemIslands *si, EnvironmentArea *ea, char *fname) {
	FILE *fileDOT;
	char buff[B_SIZE];
	int nBuff;

	list<Survivor *>::iterator it_s;
	list<StemIsland *>::iterator it_i;

	if (!checkLogLevel(Config::LOG_LOW)) return;

	snprintf(str_buff, sizeof(str_buff), "%s_%s.dot", base_filename, fname);

	fileDOT = fopen(str_buff, "w");
	if (fileDOT) {

		nBuff = snprintf(buff, B_SIZE, "graph G{\r\n");
		fwrite(buff, 1, nBuff, fileDOT);

		// stampo i quattro angoli
		nBuff = snprintf(buff, B_SIZE, "{node [style=invis] P00 P01 P10 P11}\r\n");
		fwrite(buff, 1, nBuff, fileDOT);
		nBuff = snprintf(buff, B_SIZE, "P00 [pos=\"0,0!\"]\r\n");
		fwrite(buff, 1, nBuff, fileDOT);
		nBuff = snprintf(buff, B_SIZE, "P01 [pos=\"0,%lf!\"]\r\n", (double)ea->maxY);
		fwrite(buff, 1, nBuff, fileDOT);
		nBuff = snprintf(buff, B_SIZE, "P10 [pos=\"%lf,0!\"]\r\n", (double)ea->maxX);
		fwrite(buff, 1, nBuff, fileDOT);
		nBuff = snprintf(buff, B_SIZE, "P11 [pos=\"%lf,%lf!\"]\r\n\r\n", (double)ea->maxX, (double)ea->maxY);
		fwrite(buff, 1, nBuff, fileDOT);

		nBuff = snprintf(buff, B_SIZE, "P00 -- P01\r\nP01 -- P11\r\nP11 -- P10\r\nP10 -- P00\r\n\r\n");
		fwrite(buff, 1, nBuff, fileDOT);

		// disegno tutti i punti dei sopravvissuti
		for (it_s = ea->survivors.begin(); it_s != ea->survivors.end(); it_s++) {
			if (colorList.size() > 10) {
				nBuff = snprintf(buff, B_SIZE,
						"S%i [shape=\"point\" color=\"#%06X\" pos=\"%lf,%lf!\" width=3, height=3]\r\n",
						(*it_s)->survivor_id, colorList[(*it_s)->survivor_channel],
						(*it_s)->pos.x, (*it_s)->pos.y);
			}
			else {
				nBuff = snprintf(buff, B_SIZE,
						"S%i [shape=\"point\" color=\"%s\" pos=\"%lf,%lf!\" width=3, height=3]\r\n",
						(*it_s)->survivor_id, COLOR_LIST_10[(*it_s)->survivor_channel],
						(*it_s)->pos.x, (*it_s)->pos.y);

			}
			fwrite(buff, 1, nBuff, fileDOT);
		}

		// disegno tutti i cerchi dei Stem-islands
		for (it_i = si->stem_nodes.begin(); it_i != si->stem_nodes.end(); it_i++) {

			nBuff = snprintf(buff, B_SIZE,
					"SI%i [shape=\"circle\" pos=\"%lf,%lf!\" width=%lf, height=%lf]\r\n",
					(*it_i)->stemIsland_id, (*it_i)->pos.x, (*it_i)->pos.y,
					(*it_i)->radius * 2, (*it_i)->radius * 2);

			fwrite(buff, 1, nBuff, fileDOT);
		}

		nBuff = snprintf(buff, B_SIZE, "}");
		fwrite(buff, 1, nBuff, fileDOT);

		fclose (fileDOT);
	}
}

void Printer::printOutStemIslands(StemIslands *si, EnvironmentArea *ea) {
	FILE *fileDOT;
	char buff[B_SIZE];
	int nBuff;

	list<Survivor *>::iterator it_s;
	list<StemIsland *>::iterator it_i;

	if (!checkLogLevel(Config::LOG_MEDIUM)) return;

	snprintf(str_buff, sizeof(str_buff), "%s_StemIslands.dot", base_filename);

	fileDOT = fopen(str_buff, "w");
	if (fileDOT) {

		nBuff = snprintf(buff, B_SIZE, "graph G{\r\n");
		fwrite(buff, 1, nBuff, fileDOT);

		// stampo i quattro angoli
		nBuff = snprintf(buff, B_SIZE, "{node [style=invis] P00 P01 P10 P11}\r\n");
		fwrite(buff, 1, nBuff, fileDOT);
		nBuff = snprintf(buff, B_SIZE, "P00 [pos=\"0,0!\"]\r\n");
		fwrite(buff, 1, nBuff, fileDOT);
		nBuff = snprintf(buff, B_SIZE, "P01 [pos=\"0,%lf!\"]\r\n", (double)ea->maxY);
		fwrite(buff, 1, nBuff, fileDOT);
		nBuff = snprintf(buff, B_SIZE, "P10 [pos=\"%lf,0!\"]\r\n", (double)ea->maxX);
		fwrite(buff, 1, nBuff, fileDOT);
		nBuff = snprintf(buff, B_SIZE, "P11 [pos=\"%lf,%lf!\"]\r\n\r\n", (double)ea->maxX, (double)ea->maxY);
		fwrite(buff, 1, nBuff, fileDOT);

		nBuff = snprintf(buff, B_SIZE, "P00 -- P01\r\nP01 -- P11\r\nP11 -- P10\r\nP10 -- P00\r\n\r\n");
		fwrite(buff, 1, nBuff, fileDOT);

		// disegno tutti i punti dei sopravvissuti
		for (it_s = ea->survivors.begin(); it_s != ea->survivors.end(); it_s++) {
			if (colorList.size() > 10) {
				nBuff = snprintf(buff, B_SIZE,
						"S%i [shape=\"point\" color=\"#%06X\" pos=\"%lf,%lf!\" width=3, height=3]\r\n",
						(*it_s)->survivor_id, colorList[(*it_s)->survivor_channel],
						(*it_s)->pos.x, (*it_s)->pos.y);
			}
			else {
				nBuff = snprintf(buff, B_SIZE,
						"S%i [shape=\"point\" color=\"%s\" pos=\"%lf,%lf!\" width=3, height=3]\r\n",
						(*it_s)->survivor_id, COLOR_LIST_10[(*it_s)->survivor_channel],
						(*it_s)->pos.x, (*it_s)->pos.y);

			}
			fwrite(buff, 1, nBuff, fileDOT);
		}

		// disegno tutti i cerchi dei Stem-islands
		for (it_i = si->stem_nodes.begin(); it_i != si->stem_nodes.end(); it_i++) {

			nBuff = snprintf(buff, B_SIZE,
					"SI%i [shape=\"circle\" pos=\"%lf,%lf!\" width=%lf, height=%lf]\r\n",
					(*it_i)->stemIsland_id, (*it_i)->pos.x, (*it_i)->pos.y,
					(*it_i)->radius * 2, (*it_i)->radius * 2);

			fwrite(buff, 1, nBuff, fileDOT);
		}

		nBuff = snprintf(buff, B_SIZE, "}");
		fwrite(buff, 1, nBuff, fileDOT);

		fclose (fileDOT);
	}
}

void Printer::printOutAllNodeAndSteiner(Grafo *g, int alg_idx) {
	FILE *fileDOT;
	char buff[B_SIZE];
	int nBuff;

	list<Grafo *>::iterator it_n, it_s;

	if (!checkLogLevel(Config::LOG_MEDIUM)) return;

	if (alg_idx < N_ALGO) {
		snprintf(str_buff, sizeof(str_buff), "%s_NodeAndStainers_%s.dot", base_filename, Config::ALGO_NAME[alg_idx]);
	}
	else {
		snprintf(str_buff, sizeof(str_buff), "%s_NodeAndStainers_%d.dot", base_filename, alg_idx);
	}

	fileDOT = fopen(str_buff, "w");
	if (fileDOT) {

		nBuff = snprintf(buff, B_SIZE, "graph G{\r\n");
		fwrite(buff, 1, nBuff, fileDOT);

		// stampo i quattro angoli
		nBuff = snprintf(buff, B_SIZE, "{node [style=invis] P00 P01 P10 P11}\r\n");
		fwrite(buff, 1, nBuff, fileDOT);
		nBuff = snprintf(buff, B_SIZE, "P00 [pos = \"0,0!\"]\r\n");
		fwrite(buff, 1, nBuff, fileDOT);
		nBuff = snprintf(buff, B_SIZE, "P01 [pos = \"0,%lf!\"]\r\n", (double)configuration->yMax);
		fwrite(buff, 1, nBuff, fileDOT);
		nBuff = snprintf(buff, B_SIZE, "P10 [pos = \"%lf,0!\"]\r\n", (double)configuration->xMax);
		fwrite(buff, 1, nBuff, fileDOT);
		nBuff = snprintf(buff, B_SIZE, "P11 [pos = \"%lf,%lf!\"]\r\n\r\n", (double)configuration->xMax, (double)configuration->yMax);
		fwrite(buff, 1, nBuff, fileDOT);

		//stampo prima tutti i nodi
		// siccome il grafo è connesso, posso stampare il nodo e i suoi figli
		nBuff = snprintf(buff, B_SIZE, "STEM%i [pos=\"%lf,%lf!\",shape=circle width=%i, height=%i]\r\n",
				((StemIsland *) g->nodo)->getID(), g->nodo->pos.x, g->nodo->pos.y,
				NODE_WIDTH, NODE_HEIGHT);
		fwrite(buff, 1, nBuff, fileDOT);
		for (it_n = g->figli.begin(); it_n != g->figli.end(); it_n++) {
			if((*it_n)->nodo->isSteinerNode()) {
				nBuff = snprintf(buff, B_SIZE, "STEINER%i [pos=\"%lf,%lf!\",shape=diamond width=%i, height=%i]\r\n",
						((SteinerNode *) (*it_n)->nodo)->getID(), (*it_n)->nodo->pos.x, (*it_n)->nodo->pos.y,
						NODE_WIDTH, NODE_HEIGHT);
				fwrite(buff, 1, nBuff, fileDOT);
			}
			else {
				nBuff = snprintf(buff, B_SIZE, "STEM%i [pos=\"%lf,%lf!\",shape=circle width=%i, height=%i]\r\n",
						((StemIsland *) (*it_n)->nodo)->getID(), (*it_n)->nodo->pos.x, (*it_n)->nodo->pos.y,
						NODE_WIDTH, NODE_HEIGHT);
				fwrite(buff, 1, nBuff, fileDOT);

				// stampo anche i figli steiner di tutti gli altri
				for (it_s = (*it_n)->figli.begin(); it_s != (*it_n)->figli.end(); it_s++) {
					if((*it_s)->nodo->isSteinerNode()) {
						nBuff = snprintf(buff, B_SIZE, "STEINER%i [pos=\"%lf,%lf!\",shape=diamond width=%i, height=%i]\r\n",
								((SteinerNode *) (*it_s)->nodo)->getID(), (*it_s)->nodo->pos.x, (*it_s)->nodo->pos.y,
								NODE_WIDTH, NODE_HEIGHT);
						fwrite(buff, 1, nBuff, fileDOT);
					}
				}
			}
		}

		// stampo le connessioni
		//stampo prima le connessioni degli stemnode
		if (g->nextGraph != g) { //controllo che ci siano almeno due nodi
			Grafo *baseG, *movingG;

			baseG = g;

			do {
				movingG = baseG->nextGraph;

				while (baseG != movingG) {
					nBuff = snprintf(buff, B_SIZE, "STEM%i--STEM%i\r\n",
							((StemIsland *) baseG->nodo)->getID(),
							((StemIsland *) movingG->nodo)->getID());
					fwrite(buff, 1, nBuff, fileDOT);

					movingG = movingG->nextGraph;
				}

				// per ogni nodo stampo anche le connessioni con i figli steiner
				for (it_s = baseG->figli.begin(); it_s != baseG->figli.end(); it_s++) {
					if((*it_s)->nodo->isSteinerNode()) {
						nBuff = snprintf(buff, B_SIZE, "STEM%i--STEINER%i\r\n",
								((StemIsland *) baseG->nodo)->getID(),
								((SteinerNode *) (*it_s)->nodo)->getID());
						fwrite(buff, 1, nBuff, fileDOT);
					}
				}

				baseG = baseG->nextGraph;

			} while(baseG != g);
		}

		nBuff = snprintf(buff, B_SIZE, "}");
		fwrite(buff, 1, nBuff, fileDOT);

		fclose (fileDOT);
	}
}


void Printer::printOutAllNodeAndOnlySteiner(Grafo *g, int alg_idx){
	FILE *fileDOT;
	char buff[B_SIZE];
	int nBuff;

	list<Grafo *>::iterator it_n, it_s;

	if (!checkLogLevel(Config::LOG_HIGH)) return;

	if(alg_idx < N_ALGO) {
		snprintf(str_buff, sizeof(str_buff), "%s_NodeAndOnlyStainers_%s.dot", base_filename, Config::ALGO_NAME[alg_idx]);
	}
	else {
		snprintf(str_buff, sizeof(str_buff), "%s_NodeAndOnlyStainers_%d.dot", base_filename, alg_idx);
	}

	fileDOT = fopen(str_buff, "w");
	if (fileDOT) {

		nBuff = snprintf(buff, B_SIZE, "graph G{\r\n");
		fwrite(buff, 1, nBuff, fileDOT);

		// stampo i quattro angoli
		nBuff = snprintf(buff, B_SIZE, "{node [style=invis] P00 P01 P10 P11}\r\n");
		fwrite(buff, 1, nBuff, fileDOT);
		nBuff = snprintf(buff, B_SIZE, "P00 [pos = \"0,0!\"]\r\n");
		fwrite(buff, 1, nBuff, fileDOT);
		nBuff = snprintf(buff, B_SIZE, "P01 [pos = \"0,%lf!\"]\r\n", (double)configuration->yMax);
		fwrite(buff, 1, nBuff, fileDOT);
		nBuff = snprintf(buff, B_SIZE, "P10 [pos = \"%lf,0!\"]\r\n", (double)configuration->xMax);
		fwrite(buff, 1, nBuff, fileDOT);
		nBuff = snprintf(buff, B_SIZE, "P11 [pos = \"%lf,%lf!\"]\r\n\r\n", (double)configuration->xMax, (double)configuration->yMax);
		fwrite(buff, 1, nBuff, fileDOT);

		//stampo prima tutti i nodi
		// siccome il grafo è connesso, posso stampare il nodo e i suoi figli
		nBuff = snprintf(buff, B_SIZE, "STEM%i [pos=\"%lf,%lf!\",shape=circle width=%i, height=%i]\r\n",
				((StemIsland *) g->nodo)->getID(), g->nodo->pos.x, g->nodo->pos.y,
				NODE_WIDTH, NODE_HEIGHT);
		fwrite(buff, 1, nBuff, fileDOT);
		for (it_n = g->figli.begin(); it_n != g->figli.end(); it_n++) {
			if((*it_n)->nodo->isSteinerNode()) {
				nBuff = snprintf(buff, B_SIZE, "STEINER%i [pos=\"%lf,%lf!\",shape=diamond width=%i, height=%i]\r\n",
						((SteinerNode *) (*it_n)->nodo)->getID(), (*it_n)->nodo->pos.x, (*it_n)->nodo->pos.y,
						NODE_WIDTH, NODE_HEIGHT);
				fwrite(buff, 1, nBuff, fileDOT);
			}
			else {
				nBuff = snprintf(buff, B_SIZE, "STEM%i [pos=\"%lf,%lf!\",shape=circle width=%i, height=%i]\r\n",
						((StemIsland *) (*it_n)->nodo)->getID(), (*it_n)->nodo->pos.x, (*it_n)->nodo->pos.y,
						NODE_WIDTH, NODE_HEIGHT);
				fwrite(buff, 1, nBuff, fileDOT);

				// stampo anche i figli steiner di tutti gli altri
				for (it_s = (*it_n)->figli.begin(); it_s != (*it_n)->figli.end(); it_s++) {
					if((*it_s)->nodo->isSteinerNode()) {
						nBuff = snprintf(buff, B_SIZE, "STEINER%i [pos=\"%lf,%lf!\",shape=diamond width=%i, height=%i]\r\n",
								((SteinerNode *) (*it_s)->nodo)->getID(), (*it_s)->nodo->pos.x, (*it_s)->nodo->pos.y,
								NODE_WIDTH, NODE_HEIGHT);
						fwrite(buff, 1, nBuff, fileDOT);
					}
				}
			}
		}

		// stampo le connessioni
		//stampo prima le connessioni degli stemnode
		if (g->nextGraph != g) { //controllo che ci siano almeno due nodi
			Grafo *baseG = g;

			do {
				// per ogni nodo stampo anche le connessioni con i figli steiner
				for (it_s = baseG->figli.begin(); it_s != baseG->figli.end(); it_s++) {
					if((*it_s)->nodo->isSteinerNode()) {
						nBuff = snprintf(buff, B_SIZE, "STEM%i--STEINER%i\r\n",
								((StemIsland *) baseG->nodo)->getID(),
								((SteinerNode *) (*it_s)->nodo)->getID());
						fwrite(buff, 1, nBuff, fileDOT);
					}
				}

				baseG = baseG->nextGraph;

			} while(baseG != g);
		}

		nBuff = snprintf(buff, B_SIZE, "}");
		fwrite(buff, 1, nBuff, fileDOT);

		fclose (fileDOT);
	}
}

void Printer::printOutFinalGraphWithStem(Grafo *g, int alg_idx) {
	FILE *fileDOT;
	char buff[B_SIZE];
	int nBuff;

	if (alg_idx < N_ALGO) {
		snprintf(buff, sizeof(buff), "%s_FinalTreeWithStem_%s.dot", base_filename, Config::ALGO_NAME[alg_idx]);
	}
	else {
		snprintf(buff, sizeof(buff), "%s_FinalTreeWithStem_%d.dot", base_filename, alg_idx);
	}

	if (!checkLogLevel(Config::LOG_LOW)) return;

	fileDOT = fopen(buff, "w");
	if (fileDOT) {

		nBuff = snprintf(buff, B_SIZE, "graph G{\r\n");
		fwrite(buff, 1, nBuff, fileDOT);

		//nBuff = snprintf(buff, B_SIZE, "node [fontsize=1000.0];\r\n");
		//fwrite(buff, 1, nBuff, fileDOT);

		// stampo i quattro angoli
		nBuff = snprintf(buff, B_SIZE, "{node [style=invis] P00 P01 P10 P11}\r\n");
		fwrite(buff, 1, nBuff, fileDOT);
		nBuff = snprintf(buff, B_SIZE, "P00 [pos = \"0,0!\"]\r\n");
		fwrite(buff, 1, nBuff, fileDOT);
		nBuff = snprintf(buff, B_SIZE, "P01 [pos = \"0,%lf!\"]\r\n", (double)configuration->yMax);
		fwrite(buff, 1, nBuff, fileDOT);
		nBuff = snprintf(buff, B_SIZE, "P10 [pos = \"%lf,0!\"]\r\n", (double)configuration->xMax);
		fwrite(buff, 1, nBuff, fileDOT);
		nBuff = snprintf(buff, B_SIZE, "P11 [pos = \"%lf,%lf!\"]\r\n\r\n", (double)configuration->xMax, (double)configuration->yMax);
		fwrite(buff, 1, nBuff, fileDOT);

		// stampa ricorsiva
		list<int> printedList;
		recursiveStemPrinting(fileDOT, g, buff, B_SIZE, printedList);

		nBuff = snprintf(buff, B_SIZE, "}");
		fwrite(buff, 1, nBuff, fileDOT);

		fclose (fileDOT);
	}
}

void Printer::printOutFinalGraph(Grafo *g, int alg_idx){
	char bb[B_SIZE];

	if (alg_idx < N_ALGO) {
		snprintf(bb, sizeof(bb), "%s_FinalTree_%s.dot", base_filename, Config::ALGO_NAME[alg_idx]);
	}
	else {
		snprintf(bb, sizeof(bb), "%s_FinalTree_%d.dot", base_filename, alg_idx);
	}

	printOutStandardGraph(g, bb);
}

void Printer::printOutStandardGraph(Grafo *g, char *filename) {
	FILE *fileDOT;
	char buff[B_SIZE];
	int nBuff;

	if (!checkLogLevel(Config::LOG_LOW)) return;

	fileDOT = fopen(filename, "w");
	if (fileDOT) {

		nBuff = snprintf(buff, B_SIZE, "graph G{\r\n");
		fwrite(buff, 1, nBuff, fileDOT);

		// stampo i quattro angoli
		nBuff = snprintf(buff, B_SIZE, "{node [style=invis] P00 P01 P10 P11}\r\n");
		fwrite(buff, 1, nBuff, fileDOT);
		nBuff = snprintf(buff, B_SIZE, "P00 [pos = \"0,0!\"]\r\n");
		fwrite(buff, 1, nBuff, fileDOT);
		nBuff = snprintf(buff, B_SIZE, "P01 [pos = \"0,%lf!\"]\r\n", (double)configuration->yMax);
		fwrite(buff, 1, nBuff, fileDOT);
		nBuff = snprintf(buff, B_SIZE, "P10 [pos = \"%lf,0!\"]\r\n", (double)configuration->xMax);
		fwrite(buff, 1, nBuff, fileDOT);
		nBuff = snprintf(buff, B_SIZE, "P11 [pos = \"%lf,%lf!\"]\r\n\r\n", (double)configuration->xMax, (double)configuration->yMax);
		fwrite(buff, 1, nBuff, fileDOT);

		// stampa ricorsiva
		list<int> printedList;
		recursivePrinting(fileDOT, g, buff, B_SIZE, printedList);

		nBuff = snprintf(buff, B_SIZE, "}");
		fwrite(buff, 1, nBuff, fileDOT);

		fclose (fileDOT);
	}
}

void Printer::recursiveStemPrinting(FILE *file, Grafo *g, char *buff, int buffSize, list<int> &printedList) {

	int nBuff;
	list<Grafo *>::iterator it_n;
	list<int>::iterator it_l;

	if(g->nodo == NULL) return;

	// stampo tutti i figli e poi i collegamenti con lui
	if(g->nodo->isSteinerNode()) {
		//stampo il mio steiner
		nBuff = snprintf(buff, B_SIZE, "STEINER%i [pos=\"%lf,%lf!\",shape=diamond width=%i, height=%i]\r\n",
				((SteinerNode *) g->nodo)->getID(), g->nodo->pos.x, g->nodo->pos.y,
				STEM_NODE_WIDTH, STEM_NODE_HEIGHT);
		fwrite(buff, 1, nBuff, file);

		printedList.push_back(g->nodo->getNodeID());

		for (it_n = g->figli.begin(); it_n != g->figli.end(); it_n++) {
			bool makeRecursive = true;
			int pint = (*it_n)->nodo->getNodeID();

			// controllo per evitare loop
			for (it_l = printedList.begin(); it_l != printedList.end(); it_l++) {
				if (*it_l == pint) {
					makeRecursive = false;
					break;
				}
			}

			if (makeRecursive) recursivePrinting(file, *it_n, buff, buffSize, printedList);

			if((*it_n)->nodo->isSteinerNode()) {
				nBuff = snprintf(buff, buffSize, "STEINER%i--STEINER%i\r\n",
						((SteinerNode *) g->nodo)->getID(),
						((SteinerNode *) (*it_n)->nodo)->getID());
			}
			else {
				nBuff = snprintf(buff, buffSize, "STEINER%i--STEM%i\r\n",
						((SteinerNode *) g->nodo)->getID(),
						((StemIsland *) (*it_n)->nodo)->getID());
			}
			fwrite(buff, 1, nBuff, file);
		}
	}
	else {
		//stampo il mio nodo
		nBuff = snprintf(buff, buffSize, "STEM%i [pos=\"%lf,%lf!\",shape=circle width=%i, height=%i]\r\n",
				((StemIsland *) g->nodo)->getID(), g->nodo->pos.x, g->nodo->pos.y,
				STEM_NODE_WIDTH, STEM_NODE_HEIGHT);
		fwrite(buff, 1, nBuff, file);

		printedList.push_back(g->nodo->getNodeID());

		for (it_n = g->figli.begin(); it_n != g->figli.end(); it_n++) {
			bool makeRecursive = true;
			int pint = (*it_n)->nodo->getNodeID();

			// controllo per evitare loop
			for (it_l = printedList.begin(); it_l != printedList.end(); it_l++) {
				if (*it_l == pint) {
					makeRecursive = false;
					break;
				}
			}

			if (makeRecursive) recursiveStemPrinting(file, *it_n, buff, buffSize, printedList);

			if((*it_n)->nodo->isSteinerNode()) {
				nBuff = snprintf(buff, buffSize, "STEM%i--STEINER%i\r\n",
						((StemIsland *) g->nodo)->getID(),
						((SteinerNode *) (*it_n)->nodo)->getID());
			}
			else {
				nBuff = snprintf(buff, buffSize, "STEM%i--STEM%i\r\n",
						((StemIsland *) g->nodo)->getID(),
						((StemIsland *) (*it_n)->nodo)->getID());
			}
			fwrite(buff, 1, nBuff, file);
		}
	}
}

void Printer::recursivePrinting(FILE *file, Grafo *g, char *buff, int buffSize, list<int> &printedList) {

	int nBuff;
	list<Grafo *>::iterator it_n;
	list<int>::iterator it_l;

	if(g->nodo == NULL) return;

	// stampo tutti i figli e poi i collegamenti con lui
	if(g->nodo->isSteinerNode()) {
		//stampo il mio steiner
		nBuff = snprintf(buff, B_SIZE, "STEINER%i [pos=\"%lf,%lf!\",shape=diamond width=%i, height=%i]\r\n",
				((SteinerNode *) g->nodo)->getID(), g->nodo->pos.x, g->nodo->pos.y,
				NODE_WIDTH, NODE_HEIGHT);
		fwrite(buff, 1, nBuff, file);

		printedList.push_back(g->nodo->getNodeID());

		for (it_n = g->figli.begin(); it_n != g->figli.end(); it_n++) {
			bool makeRecursive = true;
			int pint = (*it_n)->nodo->getNodeID();

			// controllo per evitare loop
			for (it_l = printedList.begin(); it_l != printedList.end(); it_l++) {
				if (*it_l == pint) {
					makeRecursive = false;
					break;
				}
			}

			if (makeRecursive) recursivePrinting(file, *it_n, buff, buffSize, printedList);

			if((*it_n)->nodo->isSteinerNode()) {
				nBuff = snprintf(buff, buffSize, "STEINER%i--STEINER%i\r\n",
						((SteinerNode *) g->nodo)->getID(),
						((SteinerNode *) (*it_n)->nodo)->getID());
			}
			else {
				nBuff = snprintf(buff, buffSize, "STEINER%i--STEM%i\r\n",
						((SteinerNode *) g->nodo)->getID(),
						((StemIsland *) (*it_n)->nodo)->getID());
			}
			fwrite(buff, 1, nBuff, file);
		}
	}
	else {
		//stampo il mio nodo
		nBuff = snprintf(buff, buffSize, "STEM%i [pos=\"%lf,%lf!\",shape=circle width=%i, height=%i]\r\n",
				((StemIsland *) g->nodo)->getID(), g->nodo->pos.x, g->nodo->pos.y,
				NODE_WIDTH, NODE_HEIGHT);
		fwrite(buff, 1, nBuff, file);

		printedList.push_back(g->nodo->getNodeID());

		for (it_n = g->figli.begin(); it_n != g->figli.end(); it_n++) {
			bool makeRecursive = true;
			int pint = (*it_n)->nodo->getNodeID();

			// controllo per evitare loop
			for (it_l = printedList.begin(); it_l != printedList.end(); it_l++) {
				if (*it_l == pint) {
					makeRecursive = false;
					break;
				}
			}

			if (makeRecursive) recursivePrinting(file, *it_n, buff, buffSize, printedList);

			if((*it_n)->nodo->isSteinerNode()) {
				nBuff = snprintf(buff, buffSize, "STEM%i--STEINER%i\r\n",
						((StemIsland *) g->nodo)->getID(),
						((SteinerNode *) (*it_n)->nodo)->getID());
			}
			else {
				nBuff = snprintf(buff, buffSize, "STEM%i--STEM%i\r\n",
						((StemIsland *) g->nodo)->getID(),
						((StemIsland *) (*it_n)->nodo)->getID());
			}
			fwrite(buff, 1, nBuff, file);
		}
	}
}

